/******************************************
 * GUIZ.cpp - defines the functions of the
 * GUIZ class.
 *
 * class for a GUI.
 *
 * Author: Jeremy Zito
 * Date:   8/19/06
 ******************************************/

#include "guiz.h"



//declare global variables


typedef window* window_ptr; 





/*----------------------------------------------------------------------------*/





/***
 * init() - initialize the gui class
 * get the font image and bind it so we can 
 * draw text fast.
 ***/
void GUIZ::init()
{
	current_tb = -1;              			 
    current_lb = -1;
     
     int x, y;
     //now load the font file
     
     //stream to read the font file from
     std::ifstream fin ("fonts/f1.mbf", std::ios::in | std::ios::binary);
     
     //extract image size
     fin.read((char*)&x, sizeof(x));
     fin.read((char*)&y, sizeof(y));

     //bind the bitmap in OpenGL
     glGenTextures(1, &font_t);
     glBindTexture(GL_TEXTURE_2D, font_t);
      

     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
     
	 char* temp = new char[x * y * 4];
     //void* temp = malloc(x * y * 4);
     //extract targa data
     fin.read((char*)temp, x * y * 4);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y,
                           0, GL_RGBA, GL_UNSIGNED_BYTE, temp);

	 delete[] temp;
     fin.close();
}





/*----------------------------------------------------------------------------*/





/***
 * create_window() - create a GUI window
 * with the specified parameters.
 * returns the index of the window.
 ***/
window_ptr GUIZ::create_window(char* name, char* skinfile, int x, int y, int w, int h)
{
    
    window win;
    
    win.wdrag = true;
    
    win.x = x;
    win.y = y;
    win.h = h;
    win.w = w;
    strcpy(win.name, name);
    win.visible = true;
	win.win_id = (1+windows.size());
    
    //find if skin has already been loaded
    bool have = false;
    for (int i = 0; i < (int)skin_names.size(); ++i)
    {
        if (skin_names[i] == skinfile)
        {
            have = true;
            win.skin = i;
            
            //get the images name for the window skin
            for (int i = 0; i < (int)skins[win.skin].size(); ++i)
            {
                win.img_names.push_back(skins[win.skin][i].name);
            }
        
            //add the window
            windows.push_back(win);
        }
    }
    if (!have)
    {
        //add the name to the list
        char temp[256];
        strcpy(temp, skinfile);
        skin_names.push_back(temp);
        
        //set the windows skin id
        win.skin = (int)skins.size();        
                
        //load the skin
        load_skin((int)windows.size(), skinfile);               
        
        //get the images name for the window skin
        for (int i = 0; i < (int)skins[win.skin].size(); ++i)
        {
            win.img_names.push_back(skins[win.skin][i].name);
        }
        
        //add the window
        windows.push_back(win);
    }
    	 
    
    focus.push_back((int)windows.size() - 1);

    
    return &windows[windows.size()-1];
}






/*----------------------------------------------------------------------------*/







/***
 * create_window() - create a GUI window
 * with the specified parameters.
 * returns the index of the window.
 * does not have a skin (invis background).
 ***/
window_ptr GUIZ::create_window(char* name, int x, int y, int w, int h)
{
    window win;
    
    win.wdrag = true;
    
    win.x = x;
    win.y = y;
    win.h = h;
    win.w = w;
    strcpy(win.name, name);
    win.visible = true;
    
    win.skin = -1;
    
    windows.push_back(win);
    
    focus.push_back((int)windows.size() - 1);

    return &windows[windows.size()-1];
}





/*----------------------------------------------------------------------------*/



/***
 * get_image_id() - get the id of an image
 * with the supplied name in the specified skin
 * returns -1 if the image is not found
 ***/
int GUIZ::get_image_id(int skin, char* image)
{
    //get the images for the button
    for (int i = 0; i < (int)skins[skin].size(); ++i)
    {
        if (strcmp(skins[skin][i].name, image) ==0)
            return i;
    }
    
    //if we couldn't find the image return -1
    return -1;
}





/*----------------------------------------------------------------------------*/





/***
 * check key events - takes the key pressed and
 * checks if any text boxes are taking input
 * returns true if test was entered into
 * a text box and false otherwise.
 ***/
bool GUIZ::check_key_event(int key)
{
	if (current_tb == -1)
		return false;

	//get the window with focus
	int win = cur_focus_window;

	textbox* tb = &windows[win].textbs[current_tb];

	//if backspace, erase a char
	if (key == 8)
	{
		if (tb->text.size() > 0)
	       tb->text.erase(tb->text.size()-1, 1);
		return true;
	}
	  
	//other wise just add the key to the string
	tb->text += (char)key;
	return true;
}





/*----------------------------------------------------------------------------*/






/***
 * check_drag_event() - checks if something 
 * is being dragged. 
 ***/
void GUIZ::check_drag_event(int x, int y)
{
     
     if (selected == -1)
       return;
     else
     {
         if(windows[selected].can_drag())
         {
             windows[selected].x += x - old_x;
             windows[selected].y += -(y - old_y);
         }
         
         
         //make sure window stays in screen
         bool move_but = true;
         /*if (windows[selected].x + windows[selected].w > viewport[2])
         {
            windows[selected].x = viewport[2] - windows[selected].w;
            move_but = false;
         }
         else if (windows[selected].x < 0)
         {
            windows[selected].x = 0;
            move_but = false;
         }
            
         if (windows[selected].y + windows[selected].h > viewport[3])
         {
            windows[selected].y = viewport[3] - windows[selected].h;
            move_but = false;
         }
         else if (windows[selected].y < 0)
         {
            windows[selected].y = 0;
            move_but = false;
         }*/
         
         if (move_but)
         {
			 //move all buttons
             for (int i = 0; i < (int)windows[selected].buttons.size(); ++i)
             {
                 if(windows[selected].can_drag())
                 {
                     windows[selected].buttons[i].x += x - old_x;
                     windows[selected].buttons[i].y += -(y - old_y);
                 }
             }

			 //move all textareas
             for (int i = 0; i< (int)windows[selected].texts.size(); ++i)
             {
                 if(windows[selected].can_drag())
                 {
                     windows[selected].texts[i].x += x - old_x;
                     windows[selected].texts[i].y += -(y - old_y);
                 }
             }

			 //move all textboxes
			 for (int i = 0; i< (int)windows[selected].textbs.size(); ++i)
             {
                 if(windows[selected].can_drag())
                 {
                     windows[selected].textbs[i].x += x - old_x;
                     windows[selected].textbs[i].y += -(y - old_y);
                 }
             }

			 //move all listboxes
			 for (int i = 0; i< (int)windows[selected].listbs.size(); ++i)
             {
                 if(windows[selected].can_drag())
                 {
                     windows[selected].listbs[i].x += x - old_x;
                     windows[selected].listbs[i].y += -(y - old_y);
                 }
             }
         }

     }
     
     //set old mouse values
     old_x = x; old_y = y;
}




/*----------------------------------------------------------------------------*/




/***
 * check_click_event() - 
 * check for click events - takes the mouse button
 * pressed (GLUT_LEFT_BUTTON or GLUT_RIGHT_BUTTON)
 * and the state of the button (GLUT_UP or GLUT_DOWN).
 * the x and y position of the mouse is also needed
 * to determine button or window clicked
 ***/
int GUIZ::check_click_event(int pbutton, int state, int x, int y)
{
     //set old mouse values
     old_x = x; old_y = y;
     
     //keep track of if we clicked something
	 //gotcha holds the id of the clicked object
     int gotcha = -1;
     
     //if focus is = -1 then there are no windows so leave func
     if ((int)focus.size()-1 == -1)
        return -1;
     
	 if (state == GLUT_DOWN)
	 {
        current_tb = -1;   //reset current textbox selected
	    current_lb = -1;   //reset current listbox selected
	 }


     //get the proper y value
     GLint viewport[4];
     glGetIntegerv (GL_VIEWPORT, viewport);
     y = viewport[3]-y;
     
     if (pbutton == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
     {     
       //sort the windows by which was clicked
       int temp;
       for (int i = (int)focus.size()-1; i >= 0; --i)
       {
          int win = focus[i];
          
          if (!windows[win].visible)
             continue;
          
          if (x > windows[win].x && x < windows[win].x + windows[win].w
              && y > windows[win].y && y < windows[win].y + windows[win].h)
          {
                 temp = focus[focus.size()-1];
                 focus[focus.size()-1] = win;
                 focus[i] = temp;
                  
                 //it has focus so...
                 //check to see if a button was clicked
                 for (int j = 0; j < (int)windows[win].buttons.size(); ++j)
                 {
                    button* but = &(windows[win].buttons[j]);
                    if(x > but->x && x < but->x + but->w  &&
                       y > but->y && y < but->y + but->h)
                    {
                          but->cur_id = but->dn_id;
                    }
                 }
					
				 //or maybe a text box was clicked...				 
				 for (int j = 0; j < (int)windows[win].textbs.size(); ++j)
                 {
					textbox* tb = &(windows[win].textbs[j]);
                    if(x > tb->x && x < tb->x + tb->w  &&
                       y > tb->y && y < tb->y + tb->h)
                    {
                          current_tb = j;						  
                    }
				 }   

				 //ooor maybe a listbox was clicked
				 for (int j = 0; j < (int)windows[win].listbs.size(); ++j)
                 {
					listbox* lb = &(windows[win].listbs[j]);
                    if(x > lb->x && x < lb->x + lb->w  &&
                       y > lb->y && y < lb->y + lb->h)
                    {
                          current_lb = j;						  
                    }
				 }  

                 cur_focus_window = win;
                 gotcha=win;
                 break;
          }      
       }
     
       //find if we can drag window
       int win = focus[focus.size()-1];
     
       
       //float scale = .095 * windows[i].h;
         
       //if (scale < 12.0)
            float scale = 15.0;
       
       if (x > windows[win].x && x < windows[win].x + windows[win].w
           && y > windows[win].y + windows[win].h - scale
           && y < windows[win].y + windows[win].h)
       {
              selected = win;
              return win;
       }      
       selected = -1;
       return gotcha;
     }
     
     if (pbutton == GLUT_LEFT_BUTTON && state == GLUT_UP)
     {  
        //reset button states
		//call function
		//return button id
        for (int i = 0; i < (int)windows[focus[focus.size()-1]].buttons.size(); ++i)
        {
           button* but = &(windows[focus[focus.size()-1]].buttons[i]);
           if (but->cur_id == but->dn_id) 
		   {
			   if (but->func_p != NULL)
                  but->func_p();
			   gotcha = (focus[focus.size()-1]+1) * 100 + i;
		   }
           but->cur_id = but->up_id;
		   
        }
        selected = -1;
     }
     
     selected = -1;
     
     return gotcha;
}




/*----------------------------------------------------------------------------*/





/***
 * draw_GUI() - render the GUI
 ***/
void GUIZ::draw_GUI()
{
     //save the current projection matrix
     glGetFloatv(GL_PROJECTION_MATRIX, proj_mat);
     //save the current model view matrix
     glGetFloatv(GL_MODELVIEW_MATRIX, modl_mat);
     //save the current viewport
     glGetIntegerv (GL_VIEWPORT, viewport);
     //save current rendering parameters
     GLboolean blend, light, depth, tex;
     glGetBooleanv(GL_BLEND, &blend);
     glGetBooleanv(GL_DEPTH_TEST, &depth);
     glGetBooleanv(GL_LIGHTING, &light);
	 glGetBooleanv(GL_TEXTURE_2D, &tex);

     
     
     //disable lighting and depth testing
     glDisable(GL_DEPTH_TEST);
     glDisable(GL_LIGHTING);
     

     //draw every window
     for (int k = 0; k < (int)focus.size(); ++k)
     {
         int i = focus[k];
         
         //continue if this window is not to be seen
         if(!windows[i].visible)
            continue;
         
           
         //set up the viewport and set to ortho
         //so we can render in 2D.
         glViewport (windows[i].x, windows[i].y, windows[i].w, windows[i].h);
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity ();
         gluOrtho2D ((double)windows[i].x, (double)windows[i].x+windows[i].w,
                     (double)windows[i].y, (double)windows[i].y+windows[i].h);

         glMatrixMode (GL_MODELVIEW);						
         glLoadIdentity ();
         
         
         //make the window transparent
         glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
         glColor4f(.85, .85, .85, .9);
         
         //float scale = .095 * windows[i].h;
         
         //if (scale < 12.0)
            float scale = 16.0;
         
         if (windows[i].skin != -1)
         {
             //enable textures    
             glEnable(GL_TEXTURE_2D);
         }
         else  //we have just a container
         {
             glDisable(GL_TEXTURE_2D);
             glColor4f(0, 0, 0, 0);
         }
           
         //draw the window geometry
         glPushMatrix();
           //draw top left
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][0].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x, 
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + windows[i].h);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x,
                        windows[i].y + windows[i].h);
           glEnd();
           
           //draw top center 
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][1].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + scale, 
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + windows[i].h);
           glEnd();
           
           //draw top right
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][2].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h - scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y + windows[i].h - scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y + windows[i].h);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h);
             glEnd();
                        
           //draw center left
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][3].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x, 
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x,
                        windows[i].y + windows[i].h-scale);
           glEnd();
           
           //draw center center 
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][4].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + scale, 
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + windows[i].h-scale);
           glEnd();
           
           //draw center right
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][5].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y + scale);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y + windows[i].h-scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + windows[i].h-scale);
           glEnd();
           
                                   
           //draw top left
           if(windows[i].skin != -1)
                glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][6].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x, 
                        windows[i].y);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x,
                        windows[i].y + scale);
           glEnd();
           
           //draw top center 
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][7].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + scale, 
                        windows[i].y);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + scale,
                        windows[i].y + scale);
           glEnd();
           
           //draw top right
           if(windows[i].skin != -1)
               glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][8].tt);
           glBegin(GL_QUADS);
             glTexCoord2f(0.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y);
             glTexCoord2f(1.0f, 0.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y);
             glTexCoord2f(1.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w,
                        windows[i].y + scale);
             glTexCoord2f(0.0f, 1.0f);
             glVertex2f(windows[i].x + windows[i].w - scale,
                        windows[i].y + scale);
           glEnd();
         glPopMatrix();
         
                  
         //draw the title of the window
         draw_text(windows[i].name, windows[i].x+5, windows[i].y + windows[i].h-13, 12);
         
         
         //draw all the buttons in the window
         glColor4f(1, 1, 1, 1);
         button but;
         for (int j = 0; j < (int)windows[i].buttons.size(); ++j)
         {
             but = windows[i].buttons[j];
             
             //draw the button geometry
             glPushMatrix();
                 glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][windows[i].buttons[j].cur_id].tt);
                 glBegin(GL_QUADS);
                    glTexCoord2f(0.0f, 0.0f);
                    glVertex2f(but.x, but.y);
                    glTexCoord2f(1.0f, 0.0f);
                    glVertex2f(but.x + but.w,
                               but.y);
                    glTexCoord2f(1.0f, 1.0f);
                    glVertex2f(but.x + but.w,
                               but.y + but.h);
                    glTexCoord2f(0.0f, 1.0f);
                    glVertex2f(but.x,
                               but.y + but.h);
                 glEnd();
             glPopMatrix();
             
             //draw the button text
             int font_size = but.h-4;
             if (font_size <= 0)
                font_size= but.h;
             draw_text(but.name, but.x+1, but.y + but.h/2-(font_size/2), font_size);
         }

		 //draw all the textboxes in the window         
         textbox tb;
		 glDisable(GL_TEXTURE_2D);
         for (int j = 0; j < (int)windows[i].textbs.size(); ++j)
         {
             tb = windows[i].textbs[j];
            
			
			 //draw highlighting box
			 glPushMatrix();   
			      glColor3ub((int)tb.rgb[0]/3, (int)tb.rgb[1]/3, (int)tb.rgb[2]/3);
                 glBegin(GL_QUADS);
                    glVertex2f(tb.x-1, tb.y);
                    glVertex2f(tb.x + tb.w,
                               tb.y);
                    glVertex2f(tb.x + tb.w,
                               tb.y + tb.h+1);
                    glVertex2f(tb.x-1,
                               tb.y + tb.h+1);
                 glEnd();
				  glColor3ub(tb.rgb[0] + (int)tb.rgb[0]/3, tb.rgb[1] + (int)tb.rgb[1]/3, tb.rgb[2] + (int)tb.rgb[2]/3);
				 glBegin(GL_QUADS);
                    glVertex2f(tb.x, tb.y-1);
                    glVertex2f(tb.x + tb.w+1,
                               tb.y-1);
                    glVertex2f(tb.x + tb.w+1,
                               tb.y + tb.h);
                    glVertex2f(tb.x,
                               tb.y + tb.h);
                 glEnd();
             glPopMatrix();
			 
			 if (i == focus[focus.size()-1] && j == current_tb)
				glColor3ub(tb.rgb[0] + (int)tb.rgb[0]/4, tb.rgb[1] + (int)tb.rgb[1]/4, tb.rgb[2] + (int)tb.rgb[2]/4);
			 else
				glColor3ub(tb.rgb[0], tb.rgb[1], tb.rgb[2]);
             //draw the textbox geometry
             glPushMatrix();                 
                 glBegin(GL_QUADS);
                    glVertex2f(tb.x, tb.y);
                    glVertex2f(tb.x + tb.w,
                               tb.y);
                    glVertex2f(tb.x + tb.w,
                               tb.y + tb.h);
                    glVertex2f(tb.x,
                               tb.y + tb.h);
                 glEnd();
             glPopMatrix();			 
             

             //draw the textbox text
             int font_size = tb.h-4;
             if (font_size <= 0)
                font_size= tb.h;
			 	
			 int num_char = (tb.w / (font_size * .625));
			 int start = 0;
			 if (((int)tb.text.size()) - num_char > 0)
				 start = tb.text.size() - num_char;
			
			 std::string temp;
			 if (((int)tb.text.size()) - start > 0)
			    temp = tb.text.substr(start, tb.text.size() - start);

             draw_text((char*)temp.c_str(), tb.x+1, tb.y + tb.h/2-(font_size/2), font_size);
         }
		 glEnable(GL_TEXTURE_2D);
         

         glColor4f(1, 1, 1, 1);
         //draw all the textareas in the window
         for (int j = 0; j < (int)windows[i].texts.size(); ++j)
         {
             textarea ta = windows[i].texts[j];
             draw_text((char*)ta.text.c_str(), ta.x, ta.y, 11);
         }

		 //draw all images in the window
		 for (int j = 0; j < (int)windows[i].gfxs.size(); ++j)
         {
			 graphic gf = windows[i].gfxs[j];
             
             //draw the button geometry
             glPushMatrix();
                 glBindTexture(GL_TEXTURE_2D, skins[windows[i].skin][windows[i].gfxs[j].skin_id].tt);
                 glBegin(GL_QUADS);
                    glTexCoord2f(0.0f, 0.0f);
                    glVertex2f(gf.x, gf.y);
                    glTexCoord2f(1.0f, 0.0f);
                    glVertex2f(gf.x + gf.w,
                               gf.y);
                    glTexCoord2f(1.0f, 1.0f);
                    glVertex2f(gf.x + gf.w,
                               gf.y + gf.h);
                    glTexCoord2f(0.0f, 1.0f);
                    glVertex2f(gf.x,
                               gf.y + gf.h);
                 glEnd();
             glPopMatrix();
		 }
     }
     glDisable(GL_TEXTURE_2D);
     
     
     
     
    //reset the projection matrix
    glViewport (viewport[0], viewport[1], viewport[2],  viewport[3]);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    glMultMatrixf(proj_mat);
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();
    glMultMatrixf(modl_mat);

	//reset environment
     if(depth)
         glEnable(GL_DEPTH_TEST);
	 else
		 glDisable(GL_DEPTH_TEST);

     if(blend)
		 glEnable(GL_BLEND);
	 else
         glDisable(GL_BLEND);

     if(light)
         glEnable(GL_LIGHTING);
	 else
		 glDisable(GL_LIGHTING);

	 if(tex)
		 glEnable(GL_TEXTURE_2D);
	 else
		 glDisable(GL_TEXTURE_2D);
}





/*----------------------------------------------------------------------------*/




/***
 * draw_text() - draw text to the screen.
 * use a bitmap texture for fast rendering.
 ***/
void GUIZ::draw_text(char* text, int x, int y, float size)
{
     //check if blending is on
     int blend;
     glGetIntegerv(GL_BLEND, &blend);
     
     //check if texture is on
     int tex;
     glGetIntegerv(GL_TEXTURE_2D, &tex);
     
     
     //enable texture
     glEnable(GL_TEXTURE_2D);
     
     //enable transparency to get rid of background
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     

	 if(strlen(text) > 0)
		 //bind the font texture
		 glBindTexture(GL_TEXTURE_2D, font_t);

     
     //declare some variables
     char* p;
     float s, t;
     float space = .0625;
     int org_x = x;
     

     glPushMatrix();
      glBegin(GL_QUADS);
        glColor3f(1, 1, 1);
        for(p = text; *p; ++p) 
        {
             if (*p == '\n')
             {
                 y -= size;
                 x = org_x;
                 continue;
             }
             
             //get the t and s values for the letter
             s = ((*p % 16) *space);
             t = ((*p / 16) *space);             
			 

             //draw
   		     glTexCoord2f(s, t);
		     glVertex2f(x, y+size);
		     glTexCoord2f(s, t+space);
		     glVertex2f(x, y);
		     glTexCoord2f(s+space, t+space);
		     glVertex2f(x+size, y);
		     glTexCoord2f(s+space, t);
		     glVertex2f(x+size, y+size);
		     
		     x += (int)(size * .625);
        }
      glEnd();
     glPopMatrix();
     
     if (!blend)
       glDisable(GL_BLEND);
       
     if (!tex)
       glDisable(GL_TEXTURE_2D);   
}







/*----------------------------------------------------------------------------*/





/***
 * load_skin() - loads the window skin
 * as 3 targa files (top, bottom, middle).
 * targa allows for transparent effects.
 * each window may have a different skin
 * so we index by window when loading.
 ***/
void GUIZ::load_skin(int win_index, char* filename)
{
     //stream to read the skin file from
     std::ifstream fin (filename, std::ios::in | std::ios::binary);
     
     //teperary image data
     image cur_img;
     
     images imgs;
     
     //get data for all window targas
     for (int i = 0; i < 9; ++i)
     {        
         //extract image data
         fin.read((char*)&cur_img, sizeof(image));
         //skins[win_index].push_back(cur_img);
         imgs.push_back(cur_img);

         //bind the bitmap in OpenGL
         glGenTextures(1, &imgs[i].tt);
         glBindTexture(GL_TEXTURE_2D, imgs[i].tt);      

         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      
         char* temp = new char[cur_img.sizeX * cur_img.sizeY * 4];
         //char* temp = (char*) malloc(cur_img.sizeX * cur_img.sizeY * 4);
         //extract targa data
         fin.read(temp, cur_img.sizeX * cur_img.sizeY * 4);
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cur_img.sizeX, cur_img.sizeY,
                           0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
		 delete[] temp;
         
     }
     
     //get the rest of the data
     int num_img;
     fin.read((char*)&num_img, sizeof(num_img));
     for (int i = 9; i < num_img; ++i)
     {
         //extract image data
         fin.read((char*)&cur_img, sizeof(image));
         //skins[win_index].push_back(cur_img);
         imgs.push_back(cur_img);
         
         //bind the bitmap in OpenGL
         glGenTextures(1, &imgs[i].tt);
         glBindTexture(GL_TEXTURE_2D, imgs[i].tt);
      

         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
      
         char* temp = new char[cur_img.sizeX * cur_img.sizeY * 4];
         //char* temp = (char*) malloc(cur_img.sizeX * cur_img.sizeY * 4);
         //extract targa data
         fin.read(temp, cur_img.sizeX * cur_img.sizeY * 4);
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cur_img.sizeX, cur_img.sizeY,
                           0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
		 delete[] temp;
     }
     
     skins.push_back(imgs);
}

